from multiprocessing.connection import Client
from typing import final

import pybloom_live
from gmpy2 import mpz
from sympy.codegen import Print
from sympy.codegen.fnodes import ubound
from sympy.core.sympify import kernS

from bloom_filter import BloomFilter
import threshold_paillier
from paillier import decryption
from threshold_paillier import rerandomize, generate_random_number, multiply_homomorphically, add_homomorphically, \
    partial_decrypt


def main():
    # 创建布隆过滤器实例
    parties_t = 3
    threshold_l=2
    client_1_set = [1, 4, 3, 2]
    client_2_set = [5, 2, 6, 3]
    server_set = [3,5,2,1]

    print("client_1_set = ",client_1_set)
    print("client_2_set = ",client_2_set)
    print("server_set = ",server_set)

    # 修改为 m_bits 和 k_hashes
    bloom_filter_1 = BloomFilter(m_bits=50, k_hashes=3)
    bloom_filter_2 = BloomFilter(m_bits=50, k_hashes=3)

    # 生成BF1
    for num in client_1_set:
        bloom_filter_1.insert(num)
    # 生成BF2
    for num in client_2_set:
        bloom_filter_2.insert(num)

    # 生成IBF1
    bloom_filter_1.invert()
    # 生成IBF2（根据你的需求）
    bloom_filter_2.invert()

    keys = threshold_paillier.key_gen(key_length=1024, threshold_l=2, parties_t=3)
    public_key = keys.public_key
    n = public_key.n
    # 份额密钥列表
    private_key = keys.private_keys  #三个参与方，有三个密钥份额
    #EIBF1 = BloomFilter(m_bits=bloom_filter_1.m_bits, k_hashes=bloom_filter_1.k_hashes)
    #EIBF2 = BloomFilter(m_bits=bloom_filter_1.m_bits, k_hashes=bloom_filter_1.k_hashes)

    EIBF1 = bloom_filter_1.threshold_paillier_encrypt_all(public_key)
    EIBF2 = bloom_filter_2.threshold_paillier_encrypt_all(public_key)

    EIBF = [EIBF1,EIBF2]
    # 对 server_set 中的元素进行处理
    total_encrypted_sum = threshold_paillier.encrypt(0, public_key)  # 初始化加密结果为 0
    C = []
    for element in server_set:
        for client in range(parties_t-1):
            for i in range(bloom_filter_1.k_hashes):  # 对每个元素进行三次哈希
                index = bloom_filter_1.hash(element, i + 1) % bloom_filter_1.m_bits
                encrypted_value = EIBF[client][index]
                total_encrypted_sum = threshold_paillier.add_homomorphically(total_encrypted_sum,encrypted_value,public_key)
        C.append(rerandomize(total_encrypted_sum,public_key))
        total_encrypted_sum = threshold_paillier.encrypt(0, public_key)  # 初始化加密结果为 0
    #C 代表标志位，C=0，代表为交集元素
    '''print(f"C = {C}")
    for i in range(len(C)):
        data1=threshold_paillier.partial_decrypt(C[i],public_key,private_key[0])
        data2=threshold_paillier.partial_decrypt(C[i],public_key,private_key[1])
        data3=threshold_paillier.partial_decrypt(C[i],public_key,private_key[2])
        s = [(mpz(1),data1),(mpz(2),data2),(mpz(3),data3)]
        f = threshold_paillier.combine_partial_decrypt(s,public_key)
        print(f"f[{i}] = {f}")'''
    #no problem

    #print(f"Dec(C) = {threshold_paillier.combine_partial_decrypt()}")
    #参与方P1和P2对C中各元素执行decryption_to_zero操作
    P = [[0] * len(C) for _ in range(parties_t-1)]  # 创建一个 parties_t-1 行和 len(C) 列的二维列表  P[2][4] 2*4
    for client in range(parties_t-1):
        for i in range(len(C)):
            r = generate_random_number(n)
            P[client][i] = multiply_homomorphically(C[i],r,public_key)
    #测试P1即可，P2与P1一致
    '''print("P1-test")
    for i in range(len(P[0])):
        data1=threshold_paillier.partial_decrypt(P[0][i],public_key,private_key[0])
        data2=threshold_paillier.partial_decrypt(P[0][i],public_key,private_key[1])
        data3=threshold_paillier.partial_decrypt(P[0][i],public_key,private_key[2])
        s = [(mpz(1),data1),(mpz(2),data2),(mpz(3),data3)]
        f = threshold_paillier.combine_partial_decrypt(s,public_key)
        print(f"f[{i}] = {f}")'''
    # no problem
    #print(f"len(P) = {len(P)}")
    #print(f"len(P[0]) = {len(P[0])}")

    #服务器将P[1],P[2]中对应的分量相乘，得到聚合new_C
    new_C = []
    temp = threshold_paillier.encrypt(0,public_key)
    for j in range(len(P[0])):
        for i in range(len(P)):
            temp = add_homomorphically(temp,P[i][j],public_key)
        new_C.append(temp)
        temp = threshold_paillier.encrypt(0,public_key)
    #new_C_test
    '''print("new_C_test")
    for i in range(len(new_C)):
        data1=threshold_paillier.partial_decrypt(new_C[i],public_key,private_key[0])
        data2=threshold_paillier.partial_decrypt(new_C[i],public_key,private_key[1])
        data3=threshold_paillier.partial_decrypt(new_C[i],public_key,private_key[2])
        s = [(mpz(1),data1),(mpz(2),data2),(mpz(3),data3)]
        f = threshold_paillier.combine_partial_decrypt(s,public_key)
        print(f"f[{i}] = {f}")'''
    #no problem
    #print(f"len(new_C) = {len(new_C)}")

    #部分解密操作partial_decryption
    client_1_private_key = private_key[0]
    client_2_private_key = private_key[1]
    server_private_key = private_key[2]

    secret_shares = []
    MPSI = []
    for i in range(len(C)):
        for client in range(parties_t):
        #for client in range(threshold_l):
            secret_shares.append((mpz(client+1),partial_decrypt(new_C[i],public_key,private_key[client])))
        decrypted_message = threshold_paillier.combine_partial_decrypt(secret_shares,public_key)
        if int(decrypted_message) == 0:
            MPSI.append(server_set[i])
        secret_shares=[]
    print("MPSI = ",MPSI)


if __name__ == "__main__":
    main()
